package com.cmc.cloud.cmclink.doc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cmc.cloud.cmclink.doc.api.document.emums.BaseCodeCategoryEnum;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;import com.cmc.cloud.cmclink.doc.vo.BaseCodeCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.BaseCodePageReqVO;
import com.cmc.cloud.cmclink.doc.vo.BaseCodeUpdateReqVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;


import java.util.*;import java.util.stream.Collectors;

import com.cmc.cloud.cmclink.doc.service.BaseCodeService;
import com.cmc.cloud.cmclink.doc.entity.BaseCodeDO;
import com.cmc.cloud.cmclink.doc.mapper.BaseCodeMapper;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BaseCodeErrorCodeConstants;


/**
 * 基础数据配置信息 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class BaseCodeServiceImpl implements BaseCodeService {

    @Resource
    private BaseCodeMapper baseCodeMapper;

    private final List<String> soList = Arrays.asList(BaseCodeCategoryEnum.SO_STATUS.getValue(), BaseCodeCategoryEnum.SO_CHANGE_STATUS.getValue());
    private final List<String> siList = Arrays.asList(BaseCodeCategoryEnum.SI_STATUS.getValue(), BaseCodeCategoryEnum.SI_AMENDMENT_STATUS.getValue());


    @Override
    @Lock4j(name = "baseCodeUnique", keys = {"#createReqVO.getCode", "#createReqVO.getCodeCategory"})
    public void createBaseCode(BaseCodeCreateReqVO createReqVO) {
        // 插入
        LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<BaseCodeDO>()
                .eqIfPresent(BaseCodeDO::getCode, createReqVO.getCode())
                .eqIfPresent(BaseCodeDO::getCodeCategory, createReqVO.getCodeCategory());

        if (baseCodeMapper.selectCount(queryWrapperX) != 0L) {
            throw ServiceExceptionUtil.exception(BaseCodeErrorCodeConstants.BASE_CODE_EXISTED);
        }
        BaseCodeDO baseCodeDO = BeanUtil.copyProperties(createReqVO, BaseCodeDO.class);
        baseCodeMapper.insert(baseCodeDO);
    }

    @Override
    @Lock4j(name = "baseCodeUnique", keys = {"#updateReqVO.getCode", "#updateReqVO.getCodeCategory"})
    public void updateBaseCode(BaseCodeUpdateReqVO updateReqVO) {
        // 校验存在
        validateBaseCodeExists(updateReqVO.getId());
        // 更新
        LambdaQueryWrapper<BaseCodeDO> queryWrapper = new LambdaQueryWrapperX<BaseCodeDO>()
                .eqIfPresent(BaseCodeDO::getCode, updateReqVO.getCode())
                .eqIfPresent(BaseCodeDO::getCodeCategory, updateReqVO.getCodeCategory())
                .ne(BaseCodeDO::getId, updateReqVO.getId());
        if (baseCodeMapper.selectCount(queryWrapper) != 0L) {
            throw ServiceExceptionUtil.exception(BaseCodeErrorCodeConstants.BASE_CODE_EXISTED);
        }
        BaseCodeDO baseCodeDO = BeanUtil.copyProperties(updateReqVO, BaseCodeDO.class);
        baseCodeMapper.updateById(baseCodeDO);
    }

    @Override
    public void deleteBaseCode(Long id) {
        // 校验存在
        validateBaseCodeExists(id);
        // 删除
        baseCodeMapper.deleteById(id);
    }


    private void validateBaseCodeExists(Long id) {
        if (baseCodeMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(BaseCodeErrorCodeConstants.BASE_CODE_NOT_EXISTS);
        }
    }

    @Override
    public BaseCodeDO getBaseCode(Long id) {
        return baseCodeMapper.selectById(id);
    }

    @Override
    public List<BaseCodeDO> getBaseCodeList(Collection<Long> ids) {
        return baseCodeMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BaseCodeDO> getBaseCodePage(BaseCodePageReqVO reqVO) {
        if (StringUtils.isEmpty(reqVO.getCodeCategory())) {
            throw ServiceExceptionUtil.exception(BaseCodeErrorCodeConstants.CODE_CATEGORY_MISS);
        }
        LambdaQueryWrapper<BaseCodeDO> queryWrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotEmpty(reqVO.getType())) {
            //so si 界面特有过滤筛选
            queryWrapper.eq(BaseCodeDO::getCodeCategory, reqVO.getType());
        } else {
            if (StringUtils.equals(reqVO.getCodeCategory(), BaseCodeCategoryEnum.SO_STATUS.getValue())) {
                queryWrapper.in(BaseCodeDO::getCodeCategory, soList);
            } else if (StringUtils.equals(reqVO.getCodeCategory(), BaseCodeCategoryEnum.SI_STATUS.getValue())) {
                queryWrapper.in(BaseCodeDO::getCodeCategory, siList);
            } else {
                queryWrapper.eq(BaseCodeDO::getCodeCategory, reqVO.getCodeCategory());
            }
        }
        if (StringUtils.isNotEmpty(reqVO.getKeyWord())) {
            queryWrapper.and(wrapper -> wrapper.like(BaseCodeDO::getCode, reqVO.getKeyWord())
                    .or().like(BaseCodeDO::getDescCn, reqVO.getKeyWord())
                    .or().like(BaseCodeDO::getDescEn, reqVO.getKeyWord()));
        }
        queryWrapper.orderByAsc(BaseCodeDO::getSortNo);
        return baseCodeMapper.selectPage(reqVO, queryWrapper);
    }

    @Override
    public PageResult<BaseCodeDO> getEnabledBaseCodePage(BaseCodePageReqVO pageReqVO) {
        if (StringUtils.isEmpty(pageReqVO.getCodeCategory())) {
            throw ServiceExceptionUtil.exception(BaseCodeErrorCodeConstants.CODE_CATEGORY_MISS);
        }
        LambdaQueryWrapper<BaseCodeDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(BaseCodeDO::getEnable,true);

        if (StringUtils.isNotEmpty(pageReqVO.getType())) {
            //so si 界面特有过滤筛选
            queryWrapper.eq(BaseCodeDO::getCodeCategory, pageReqVO.getType());
        } else {
            if (StringUtils.equals(pageReqVO.getCodeCategory(), BaseCodeCategoryEnum.SO_STATUS.getValue())) {
                queryWrapper.in(BaseCodeDO::getCodeCategory, soList);
            } else if (StringUtils.equals(pageReqVO.getCodeCategory(), BaseCodeCategoryEnum.SI_STATUS.getValue())) {
                queryWrapper.in(BaseCodeDO::getCodeCategory, siList);
            } else {
                queryWrapper.eq(BaseCodeDO::getCodeCategory, pageReqVO.getCodeCategory());
            }
        }
        if (StringUtils.isNotEmpty(pageReqVO.getKeyWord())) {
            queryWrapper.and(wrapper -> wrapper.like(BaseCodeDO::getCode, pageReqVO.getKeyWord())
                    .or().like(BaseCodeDO::getDescCn, pageReqVO.getKeyWord())
                    .or().like(BaseCodeDO::getDescEn, pageReqVO.getKeyWord()));
        }
        queryWrapper.orderByAsc(BaseCodeDO::getSortNo);
        return baseCodeMapper.selectPage(pageReqVO, queryWrapper);
    }

    @Override
    public List<BaseCodeDO> getBaseCodeListByType(String codeCategory) {
        List<BaseCodeDO> baseCodeDos = baseCodeMapper.selectList(new LambdaQueryWrapper<BaseCodeDO>().eq(BaseCodeDO::getCodeCategory, codeCategory));
        return baseCodeDos;
    }

    @Override
    public Map<String, String> getShipCodeNameEn(List<String> codes) {
        if (CollectionUtils.isEmpty(codes)) {
            return CollectionUtils.newHashMap();
        }
         LambdaQueryWrapperX<BaseCodeDO> queryWrapperX = new LambdaQueryWrapperX<>();
         queryWrapperX.eq(BaseCodeDO::getCodeCategory, BaseCodeCategoryEnum.SHIPPING_TERM.getValue())
            .in(BaseCodeDO::getCode, codes);
         List<BaseCodeDO> baseCodeList = baseCodeMapper.selectList(queryWrapperX);
         Map<String, String> codeNameMap = new HashMap<>(16);
         if (!CollectionUtils.isEmpty(baseCodeList)) {
            codeNameMap = baseCodeList.stream().collect(Collectors.toMap(BaseCodeDO::getCode, BaseCodeDO::getDescEn, (v1, v2) -> v1));
         }
        return codeNameMap;
    }

}
